#ifndef CVOBJECTSUBSYSTEM_H_INCLUDED
#define CVOBJECTSUBSYSTEM_H_INCLUDED

#include <SubSystemBase/ISubSystem.h>
#include <Logger/ILogger.h>
#include "BaseObject.h"
#include "EmptyObject.h"

/** Enumeration of gameobject types */
enum
{
	GAMEOBJECT_BASE = 1,		/** The proberties object */
	GAMEOBJECT_EMPTY,			/** Classic moveable point in game world */
	GAMEOBJECT_PHYSICS,			/** Physics simulation object, 'invisible shape' */
	GAMEOBJECT_CAMERA,			/** The CameraObject */
	GAMEOBJECT_MOUSE, 			/** Object that act as mouse cursor in game-engine */
	GAMEOBJECT_SPRITE,			/** Classic simple sprite objects */
	GAMEOBJECT_DRAWING,			/** Object can be any of renderable primitives */
	GAMEOBJECT_WORLD,			/** Ultimate gameworld resource object */
	RESOURCEOBJ_IMAGE,			/** Resource objects */
	RESOURCEOBJ_COLLIDESHAPE,
	RESOURCEOBJ_MAPDATA
};

typedef void (*cleanmemproc_t)();


class ObjectSubSystem : public ISubSystem
{
public:

	static const char* SUBSYSTEMNAME;

	ObjectSubSystem();
	virtual ~ObjectSubSystem();

	/**
	 * Initializes the subsystem. If either an exception is thrown or the method returns false,
	 * the SubSystemManager will stop further initialization of subsystems, shutdown the
	 * already initialized subsystems and then the whole execution environment with error message.
	 * @throws Exception, possibly
	 * @return true, if the subsystem was successfully initialized, otherwise false
	 */
	virtual bool initialize();

	/**
	 * Releases subsystem-specific resources and shuts down the subsystem.
	 * Called by SubSystemManager when the execution environment is being shut down.
	 */
	virtual void shutdown();

	/**
	 * Returns is the subsystem initialized or not
	 * @return true, if the subsystem is initialized, otherwise false
	 */
	virtual bool isInitialized() { return m_initialized; }

	/**
	 * Changes the subsystem configuration to match given configuration.
	 * @throws InvalidConfigurationException, if the configuration isn't valid for this subsystem.
	 */
	//virtual void configure(IConfiguration& config) = 0;

	/**
	 * Returns the name of this subsystem as c-string (null-terminated char-array)
	 * @return Name of the subsystem
	 */
	virtual const char* getName() { return SUBSYSTEMNAME; }

	/**
	 * Sets the logger this subsystem should use
	 * @param logger	Logger to use
	 */
	virtual void setLogger(ILogger* logger) { m_logger = logger; }

	/**
	 * Returns the logger used by this subsystem
	 */
	virtual ILogger* getLogger() { return m_logger; }


	/**
	 *	Returns global instance of the ObjectSubSystem
	 */
	static ObjectSubSystem * getInstance();

	/**
	 *	Object Creation.
	 */
	template<typename T> T * create()
	{
		using namespace cvObjects;
		T * obj = T::create();
		obj->listItr = m_objectlist.insert(m_objectlist.end(), obj);
		return obj;
	}

	/**
	 *	Object Destruction.
	 */
	void deleteObject(cvObjects::BaseObject * obj);
	/** Destroy all objectes. ALL 'OBJECTS'.
	 *	Only the camera objectes survive from this, because their ownership belongs to RenderSubSystem. */
	void destroyAllObjects();

	/**
	 *	Updates the ObjectSubSystem.
	 */
	void updateObjects();

	/**
	 *	Iterate through the global object list
	 */
	void resetObjectIterator();
	cvObjects::BaseObject * getNextObject();
	cvObjects::BaseObject * getPrevObject();

private:
	// Linear, Random Access and Direct access of objects, both containers are pooled.

	//typedef boost::unordered_map<BaseObject*, baseobj_list_t::iterator, boost::hash<BaseObject*>, std::equal_to<BaseObject*>,
	//		cvPoolAllocator<std::pair<BaseObject*, baseobj_list_t::iterator> >::CON >	obj_hashmap_t;

	bool m_initialized;
	static ObjectSubSystem * m_subsystem;

	/// Object storgate.
	baseobj_list_t m_objectlist;
	//obj_hashmap_t m_objectmap;		// gameobject pointter -> iterator.
	baseobj_list_t::iterator m_objectlist_glb_it;

	/// List of memory pool cleaners
	static std::vector<cleanmemproc_t> m_purgesystem_mem;
};

#endif /* CVOBJECTSUBSYSTEM_H_INCLUDED */
